﻿using System;
using System.IO;
using PortableVersion.Core.General;

namespace PortableVersion.Core.FileSystem
{
    [Flags]
    public enum FileCopyOptions{ Overwrite = 1, CreateFolder=2, KeepTargetCreatedTime=4 }
    public class FsoService : IFsoService
    {
        public void CopyFile(string fromPath, string toPath, FileCopyOptions options, Func<bool> continueOnExists = null)
        {
            fromPath.AssertNotNull("fromPath");
            toPath.AssertNotNull("toPath");
            var source = new FileInfo(fromPath);
            var targetCreationTime = default(DateTime?);
            if (File.Exists(toPath))
            {
                targetCreationTime = File.GetCreationTimeUtc(toPath);
                if (((options & FileCopyOptions.Overwrite) == 0) && continueOnExists != null && !continueOnExists())
                    throw new FileLoadException(String.Format(@"File '{0}' already exists.", toPath));
            }
            if ((options & FileCopyOptions.CreateFolder) != 0)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(toPath));
            }
            File.Copy(fromPath, toPath, true);
            if (targetCreationTime.HasValue)
                File.SetCreationTimeUtc(toPath, targetCreationTime.Value);
        }
 
        public void CopyFile(FileItem from, FileItem to, FileCopyOptions options, Func<bool> continueOnExists = null)
        {
            if (to.NullSafe(t => t.Path) == null)
            {
                throw new ArgumentNullException("to");
            }
            if ((options&FileCopyOptions.KeepTargetCreatedTime)!=0 && to.Position == FilePosition.Slave)
            {
                throw new ArgumentException(String.Format(@"Copy options set to keep target created time is not valid if target is a slave."));
            }
            CopyFile(from.Path, to.Path, options, continueOnExists);
            if (to.Position != FilePosition.Slave) return;
            File.SetAttributes(to.Path, FileAttributes.Normal);
            File.SetCreationTimeUtc(to.Path, to.CreatedDate);
            File.SetLastWriteTimeUtc(to.Path, to.ModifiedDate);
        }

        public DirectoryInfo GetDirectoryInfo(string path)
        {
            return new DirectoryInfo(path);
        }

        public void CreateDirectory(string path)
        {
            Directory.CreateDirectory(path);
        }

        public void SetDirectoryCreationTimeUtc(string path, DateTime time)
        {
            Directory.SetCreationTimeUtc(path, time);
        }

        public void SetDirectoryModifiedTeimeUtc(string path, DateTime dateTime)
        {
            Directory.SetLastWriteTimeUtc(path, dateTime);
        }

        public void DeleteFile(string path)
        {
            File.Delete(path);
        }
    }
}
